/*
 * Copyright 2020-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.naja.auth2clientfirst.support;

import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;

import java.util.List;

/**
 * 整合客户端自有权限列表
 *
 * @author Steve Riesenberg
 * @since 0.2.3
 */
public final class FederatedAuthorityConfigurer extends AbstractHttpConfigurer<FederatedAuthorityConfigurer, HttpSecurity> {

    @Override
    public void init(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
        authenticationManagerBuilder.objectPostProcessor(new ObjectPostProcessor<Object>() {
            @Override
            public Object postProcess(Object providerManager) {
                List<AuthenticationProvider> providers = null;
                try {
                    providers = ((ProviderManager) providerManager).getProviders();
                    //提供通过cookie/session产生的OAuth2AuthenticationToken进行整合客户端自有权限
                    providers.add(new OAuth2AuthenticationTokenProvider());
                    return providerManager;
                } finally {
                    //提供对未识别的认证信息类型的支持,否则登录信息会丢失,SimpleTokenProvider必须放在最后,providers是有序的
                    providers.add(new SimpleTokenProvider());
                }
            }
        })
        ;
        http.authorizeRequests(authorizeRequests ->
                authorizeRequests
                        .withObjectPostProcessor(new ObjectPostProcessor<AbstractSecurityInterceptor>() {
                            @Override
                            public AbstractSecurityInterceptor postProcess(AbstractSecurityInterceptor abstractSecurityInterceptor) {
                                //配置重新处理认证信息,以支持整合客户端自定义的权限
                                abstractSecurityInterceptor.setAlwaysReauthenticate(true);
                                return abstractSecurityInterceptor;
                            }
                        }));
    }

}
